const path = require('path');

const gulp = require('gulp');
const del = require('del');
const babel = require('gulp-babel');
const terser = require('gulp-terser');
const htmlmin = require('gulp-htmlmin');
const postcss = require('gulp-postcss');
const postcssNext = require('postcss-preset-env');
const postcssPresetEnv = require('postcss-preset-env');
const cssnano = require('gulp-cssnano');
const stylelint = require('gulp-stylelint');
const imagemin = require('gulp-imagemin');
const rename = require('gulp-rename');
const rev = require('gulp-rev');
const revCollector = require('gulp-rev-collector');
const revFormat = require('gulp-rev-format');
const cache = require('gulp-cache');
const copy = require('gulp-copy');

const src = path.resolve(__dirname, 'src');
const build = path.resolve(__dirname, 'build');
const temp = path.resolve(__dirname, 'build/temp');

const imageDir = 'img';
const jsDir = 'js';
const cssDir = 'css';
const staticDir = 'static';
const libDir = 'lib';

/**
 * 图片任务
 * hash，min
 * @returns {*}
 */
function imageTask() {
    return gulp.src(`${src}/${imageDir}/**/*.{jpg,png,svg,gif}`)
        .pipe(rev())
        .pipe(revFormat({
            prefix: ".",
            suffix: "",
            lastExt: false
        }))
        .pipe(cache(
            imagemin([
                imagemin.gifsicle({interlaced: true}),
                imagemin.mozjpeg({quality: 80, progressive: true}),
                // imagemin.optipng({optimizationLevel: 5})
                ],
                {verbose: true}
            )
        ))
        .pipe(gulp.dest(`${build}/${imageDir}`))
        .pipe(rev.manifest('../rev/rev-img-manifest.json'))
        .pipe(gulp.dest(`${build}/${imageDir}`));
}

/**
 * 静态资源任务
 * hash，min
 * @returns {*}
 */
function staticTask() {
  return gulp.src(`${src}/${staticDir}/**/*.{woff,woff2,aac,mp3}`)
    .pipe(rev())
    .pipe(revFormat({
      prefix: ".",
      suffix: "",
      lastExt: false
    }))
    .pipe(gulp.dest(`${build}/${staticDir}`))
    .pipe(rev.manifest('../rev/rev-static-manifest.json'))
    .pipe(gulp.dest(`${build}/${staticDir}`));
}

/**
 * 根据manifest替换js引用资源
 * 生成temp/*.js
 *
 * @returns {*}
 */
function revCollectorJsTask() {
    return gulp.src([`${build}/rev/rev-*.json`, `${src}/${jsDir}/*.js`])
        .pipe(revCollector({
            revSuffix: '.[0-9a-f]{8,10}(.min)?',
            replaceReved: true
        }))
        .pipe(gulp.dest(`${temp}/${jsDir}`));
}
/**
 * js任务
 * babel，压缩，hash
 * @returns {*}
 */
function jsTask() {
    return gulp.src(`${temp}/${jsDir}/*.js`)
        .pipe(babel({
            presets: ['@babel/env']
        }))
        .pipe(rev())
        .pipe(revFormat({
            prefix: ".",
            suffix: "",
            lastExt: false
        }))
        .pipe(gulp.dest(`${build}/${jsDir}`))
        .pipe(terser())
        .pipe(rename({
            suffix: '.min',
        }))
        .pipe(gulp.dest(`${build}/${jsDir}`))
        .pipe(rev.manifest({
            path: '../rev/rev-js-manifest.json',
            merge: true
        }))
        .pipe(gulp.dest(`${build}/${jsDir}`));
}

/**
 * 根据manifest替换css引用资源
 *
 * @returns {*}
 */
function revCollectorCssTask() {
    return gulp.src([`${build}/rev/rev-*.json`, `${src}/${cssDir}/*.css`])
        .pipe(revCollector({
            revSuffix: '.[0-9a-f]{8,10}(.min)?',
            replaceReved: true
        }))
        .pipe(gulp.dest(`${temp}/${cssDir}`));
}

/**
 * css任务
 * 压缩，hash
 * @returns {*}
 */
function cssTask() {
    let plugins = [postcssPresetEnv({
        autoprefixer: {grid: true},
        //browsers: '> 0.02%',
        stage: 4,
        features: { // true：填充这些特性，false：保留
            'custom-properties': true,
            'all-property': true
        },
        preserve: false,    //填充的方式，true：保留原有，false：替换
    })];

    return gulp.src(`${temp}/${cssDir}/*.css`)
        .pipe(postcss(plugins))
        .pipe(rev())
        .pipe(revFormat({
            prefix: ".",
            suffix: "",
            lastExt: false
        }))
        .pipe(gulp.dest(`${build}/${cssDir}`))
        .pipe(cssnano())
        .pipe(rename({
            suffix: '.min'
        }))
        .pipe(gulp.dest(`${build}/${cssDir}`))
        .pipe(rev.manifest({
            path: '../rev/rev-css-manifest.json',
            merge: true
        }))
        .pipe(gulp.dest(`${build}/${cssDir}`));
}

/**
 * html任务
 * 替换manifest内容，压缩
 * @returns {*}
 */
function htmlTask() {
    return gulp.src([`${build}/rev/rev-*.json`, `${src}/*.html`])
        .pipe(revCollector({
            revSuffix: '.[0-9a-f]{8,10}(.min)?',
            replaceReved: true
        }))
        .pipe(htmlmin({
                removeComments: true,
                collapseWhitespace: true,
                minifyCSS: true,
                minifyJS: true
            }
        ))
        .pipe(gulp.dest(`${build}`));
}

function copyLibs() {
    return gulp.src(`${src}/${libDir}/*`).pipe(gulp.dest(`${build}/${libDir}`));
}

/**
 * 拷贝静态资源
 */
function copyStatic() {
    const sourceFiles = [`./src/${staticDir}/*`];
    return gulp.src(sourceFiles)
        .pipe(copy('build/', {prefix: 1}));
}

function cleanTask() {
    return del(`${build}`);
}

function cleanTemp() {
    return del(`${temp}`)
}

function clearCache() {
    return cache.clearAll();
}

exports.clean = cleanTask;
exports.imageTask = imageTask;
exports.jsTask = jsTask;
exports.cssTask = cssTask;
exports.htmlTask = htmlTask;
exports.clear = clearCache;
exports.build = gulp.series(cleanTask,
    imageTask, staticTask,
    revCollectorJsTask, jsTask,
    revCollectorCssTask, cssTask,
    htmlTask, copyLibs,
    cleanTemp);
